fatal_trap(TRAP_machine_check, regs);
}
-asmlinkage int do_page_fault(struct xen_regs *regs)
+void propagate_page_fault(unsigned long addr, u16 error_code)
{
trap_info_t *ti;
+ struct domain *d = current;
+ struct trap_bounce *tb = &d->thread.trap_bounce;
+
+ ti = d->thread.traps + 14;
+ tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
+ tb->cr2 = addr;
+ tb->error_code = error_code;
+ tb->cs = ti->cs;
+ tb->eip = ti->address;
+ if ( TI_GET_IF(ti) )
+ d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
+}
+
+asmlinkage int do_page_fault(struct xen_regs *regs)
+{
unsigned long off, addr, fixup;
struct domain *d = current;
extern int map_ldt_shadow_page(unsigned int);
- struct trap_bounce *tb = &d->thread.trap_bounce;
int cpu = d->processor;
__asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
if ( !GUEST_FAULT(regs) )
goto xen_fault;
- ti = d->thread.traps + 14;
- tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
- tb->cr2 = addr;
- tb->error_code = regs->error_code;
- tb->cs = ti->cs;
- tb->eip = ti->address;
- if ( TI_GET_IF(ti) )
- d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
+ propagate_page_fault(addr, regs->error_code);
return 0;
xen_fault:
/*
* Called from the general-protection fault handler to attempt to decode
- * and emulate an instruction that depends on 4GB segments. At this point
- * we assume that the instruction itself is paged into memory (the CPU
- * must have triggered this in order to decode the instruction itself).
+ * and emulate an instruction that depends on 4GB segments.
*/
int gpf_emulate_4gb(struct xen_regs *regs)
{
if ( get_user(b, pb) )
{
DPRINTK("Fault while accessing byte %d of instruction\n", pb-eip);
- goto fail;
+ goto page_fault;
}
if ( (pb - eip) >= 15 )
switch ( decode & 7 )
{
case 1:
- offset = (long)(*(char *)pb);
+ if ( get_user(b, pb) )
+ {
+ DPRINTK("Fault while extracting <moffs8>.\n");
+ goto page_fault;
+ }
+ pb++;
+ offset = (signed long)(signed char)b;
goto skip_modrm;
case 4:
- offset = *(long *)pb;
+ if ( get_user(offset, (u32 *)pb) )
+ {
+ DPRINTK("Fault while extracting <disp8>.\n");
+ goto page_fault;
+ }
+ pb += 4;
goto skip_modrm;
default:
goto fail;
if ( get_user(modrm, pb) )
{
DPRINTK("Fault while extracting modrm byte\n");
- goto fail;
+ goto page_fault;
}
pb++;
if ( get_user(disp32, (u32 *)pb) )
{
DPRINTK("Fault while extracting <disp8>.\n");
- goto fail;
+ goto page_fault;
}
pb += 4;
}
if ( get_user(disp8, pb) )
{
DPRINTK("Fault while extracting <disp8>.\n");
- goto fail;
+ goto page_fault;
}
pb++;
disp32 = (disp8 & 0x80) ? (disp8 | ~0xff) : disp8;;
if ( get_user(disp32, (u32 *)pb) )
{
DPRINTK("Fault while extracting <disp8>.\n");
- goto fail;
+ goto page_fault;
}
pb += 4;
break;
d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
}
- return 1;
+ return EXCRET_fault_fixed;
fixme:
DPRINTK("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
regs->cs, regs->eip);
fail:
return 0;
+
+ page_fault:
+ propagate_page_fault((unsigned long)pb, 4);
+ return EXCRET_fault_fixed;
}